<?php
/**
 * 蜗牛博客
 * 本文件内代码属于“蜗牛博客”项目，禁止修改再发布本程序源码，禁止去除页面底部的版权申明。所有版权保留
 * User: upliu
 * Email: 753073861@qq.com
 * QQ: 753073861
 * 程序主页：http://demo.upliu.net/snail-blog/
 */

define('USER_STATUS_ACTIVE', 10);
define('USER_STATUS_FORBIDDEN', 20);

define('RETURN_STATUS_SUCCESS', 0);
define('RETURN_STATUS_FAIL', 1);

define('POST_STATUS_PUBLISH', 0b00000001); // 文章状态 已发布
define('POST_STATUS_DRAFT', 0b00000010); // 文章状态 草稿
define('POST_STATUS_TRASH', 0b00000100); // 文章状态 回收站

define('COMMENT_STATUS_OPEN', 1);
define('COMMENT_STATUS_CLOSE', 0);

define('CATEGORY_ID_DEFAULT', 1);

class Option
{
    protected static $values;
    public static function get($key, $default = '')
    {
        if (null === static::$values) {
            $db = Db::getInstance();
            $options = $db->queryAll("select `key`,`value` from `option`");
            foreach ($options as $o) {
                static::$values[$o['key']] = $o['value'];
            }
        }

        if (isset(static::$values[$key])) {
            return static::$values[$key];
        }

        static::$values[$key] = $default;

        return $default;
    }

    public static function set($key, $value)
    {
        if ($value != static::get($key)) {
            $db = Db::getInstance();
            $db->update('option', array('value' => $value), "`key`=?", $value);
            static::$values[$key] = $value;
        }
    }
}

function admin_layout_navs()
{
    static $navs;
    if (null !== $navs) {
        return $navs;
    }
    $navs = array(
        new Nav(array(
            'label' => '博客',
            'subNavs' => array(
                new Nav(array(
                    'href' => 'post-new.php',
                    'label' => '写文章',
                )),
                new Nav(array(
                    'href' => 'post.php',
                    'label' => '文章管理',
                )),
                new Nav(array(
                    'href' => 'comment.php',
                    'label' => '评论管理',
                )),
                new Nav(array(
                    'href' => 'category.php',
                    'label' => '分类管理',
                )),
                new Nav(array(
                    'href' => 'tag.php',
                    'label' => '标签管理',
                )),
            ),
        )),
        new Nav(array(
            'label' => '小工具',
            'subNavs' => array(
                new Nav(array(
                    'href' => 'about.php',
                    'label' => '关于',
                )),
                new Nav(array(
                    'href' => 'link.php',
                    'label' => '友情链接',
                )),
            ),
        )),
        new Nav(array(
            'label' => '设置',
            'subNavs' => array(
                new Nav(array(
                    'href' => 'option.php',
                    'label' => '设置',
                )),
                new Nav(array(
                    'href' => 'profile.php',
                    'label' => '个人资料',
                )),
//                new Nav(array(
//                    'href' => 'user.php',
//                    'label' => '用户管理',
//                    'show' => is_current_login_user_super_admin(),
//                )),
            ),
        )),
        new Nav(array(
            'label' => '开飞机的小蜗牛',
            'type' => Nav::TYPE_HREF,
            'href' => 'https://upliu.net/',
            'target' => '_blank',
        )),
    );

    return $navs;
}

function comment_add($author, $content, $post_id, $parent_id = 0)
{
    $db = Db::getInstance();
    $db->insert('comment', array(
        'comment_post_id' => $post_id,
        'comment_author' => $author,
        'comment_content' => $content,
        'comment_parent' => (int)$parent_id,
        'comment_author_ip' => get_client_ip(),
        'comment_date' => date('Y-m-d H:i:s'),
    ));
    $db->execute("update post set comment_count=comment_count+1 where id=?", $post_id);
}

function post_default()
{
    return array(
        'post_status' => POST_STATUS_PUBLISH,
        'comment_status' => COMMENT_STATUS_OPEN,
    );
}

function post_save($_data)
{
    $columns = 'id,post_author_id,post_date,post_content,post_title,post_status,post_password,post_modified,comment_status,comment_count,category_id';
    $data = array();
    foreach (explode(',', $columns) as $c) {
        if (isset($_data[$c])) {
            $data[$c] = $_data[$c];
        }
    }
    $db = Db::getInstance();
    if (empty($data['category_id'])) {
        unset($data['category_id']);
    }
    $data = array_merge(array(
        'comment_status' => COMMENT_STATUS_CLOSE,
        'category_id' => CATEGORY_ID_DEFAULT,
    ), $data);
    if (empty($data['id'])) {
        unset($data['id']);
        $data['post_date'] = date('Y-m-d H:i:s');
        $data['id'] = $db->insert('post', $data);
        $db->execute("update category set item_count=item_count+1 where id=?", $data['category_id']);
    } else {
        $data['post_modified'] = date('Y-m-d H:i:s');
        $old_category_id = $db->queryColumn("select category_id from post where id=?", $data['id']);
        $db->update('post', $data, 'id=?', $data['id']);
        if ($old_category_id != $data['category_id']) {
            $db->execute("update category set item_count=item_count-1 where id=?", $old_category_id);
            $db->execute("update category set item_count=item_count+1 where id=?", $data['category_id']);
        }
    }

    $tag_names = array_filter(explode(',', $_data['tag']), 'trim');
    $rows = $db->queryAllWhereIn("select id,name from tag", 'name', $tag_names);
    $tags = array_column($rows, 'name', 'id');
    foreach ($tag_names as $n) {
        if (!in_array($n, $tags)) {
            $tag_id = $db->insert('tag', array('name' => $n));
            $tags[$tag_id] = $n;
        }
    }
    $rows = $db->queryAll("select tag_id from map_post_tag where post_id=?", $data['id']);
    $old_tag_ids = array_column($rows, 'tag_id');
    $new_tag_ids = array_keys($tags);
    foreach (array_diff($new_tag_ids, $old_tag_ids) as $tag_id) {
        $db->insert('map_post_tag', array(
            'post_id' => $data['id'],
            'tag_id' => $tag_id,
        ));
        $db->execute("update tag set item_count=item_count+1 where id=?", $tag_id);
    }
    foreach (array_diff($old_tag_ids, $new_tag_ids) as $tag_id) {
        $db->delete('map_post_tag', 'post_id=? and tag_id=?', array(
            $data['id'],
            $tag_id,
        ));
        $db->execute("update tag set item_count=item_count-1 where id=?", $tag_id);
    }

    return $data['id'];
}

function post_month_all()
{
    static $result;
    if (null !== $result) {
        return $result;
    }
    $db = Db::getInstance();
    $rows = $db->queryAll("select distinct DATE_FORMAT(post_date, '%Y-%m') as _date from post order by id desc");
    $months = array_column($rows, '_date');
    $map = array(
        1 => '一',
        2 => '二',
        3 => '三',
        4 => '四',
        5 => '五',
        6 => '六',
        7 => '七',
        8 => '八',
        9 => '九',
        10 => '十',
        11 => '十一',
        12 => '十二',
    );
    $result = array();
    foreach ($months as $m) {
        $u = explode('-', $m);
        $result[$m] = $u[0] . '年' . $map[intval($u['1'])] . '月';
    }

    return $result;
}

function category_get_name_by_id($id)
{
    return Db::getInstance()->queryColumn("select name from category where id=?", $id);
}

function category_all()
{
    static $categorys;
    if (null === $categorys) {
        $db = Db::getInstance();
        $rows = $db->queryAll('select id,name,pid from category');
        $_categorys = tree($rows);
        foreach ($_categorys as $cat) {
            $categorys[$cat['id']] = str_repeat('&nbsp;', $cat['level']*2) . $cat['name'];
        }
    }

    return $categorys;
}

function tree($items, $pid = 0, $level = 0)
{
    static $tree = array();
    foreach ($items as $item) {
        if ($item['pid'] == $pid) {
            $item['level'] = $level;
            $tree[] = $item;
            tree($items, $item['id'], $level+1);
        }
    }
    return $tree;
}

function image_delete($id)
{
    $db = Db::getInstance();
    $path = $db->queryColumn("select path from image where id=?", $id);
    unlink(ROOTPATH.Option::get('UPLOAD_PATH', '/uploads').$path);
    $db->delete('image', 'id=?', $id);
}

function image_upload($field_name)
{
    $file = $_FILES[$field_name];
    $t = explode('/', $file['type']);
    if (isset($t[0]) && $t[0] == 'image') {
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (empty($ext) || !in_array($ext, explode(',', 'jpg,jpeg,png,gif,ico'))) {
            return false;
        }
        $filename = uniqid() . '.' . $ext;
        $path = date('/Y/m-d/') . $filename;
        $uploadPath = Option::get('UPLOAD_PATH', '/uploads');
        $filePath = ROOTPATH.$uploadPath.$path;
        if (!file_exists($dir = dirname($filePath))) {
            mkdir($dir, 0755, true);
        }
        $imgUrl = get_url($uploadPath.$path);
        move_uploaded_file($file['tmp_name'], $filePath);
        $db = Db::getInstance();
        $id = $db->insert('image', array(
            'path' => $path,
            'upload_user_id' => get_current_login_user_info('id'),
            'upload_time' => date('Y-m-d H:i:s'),
        ));
        return array(
            'id' => $id,
            'url' => $imgUrl,
            'filename' => $filename
        );
    }

    return false;
}

function is_installed()
{
    return file_exists(__DIR__ . '/../config.php');
}

function get_user_status_desc($status)
{
    $map = array(
        USER_STATUS_ACTIVE => '启用',
        USER_STATUS_FORBIDDEN => '禁用',
    );

    return $map[$status];
}

function logout()
{
    unset($_SESSION['user']);
}

function check_login()
{
    if (!is_login()) {
        redirect_path(get_admin_home_path() . '/login.php');
    }
}

function is_login()
{
    return !empty($_SESSION['user']);
}

function get_current_login_user_info($key = null)
{
    $user = $_SESSION['user'];
    if ($key) {
        return $user[$key];
    }

    return $user;
}

function is_current_login_user_super_admin()
{
    return get_current_login_user_info('is_admin');
}

function user_login($username, $input_password)
{
    $user = find_user_by_username($username);
    if (!$user) {
        return array('status' => RETURN_STATUS_FAIL, 'message' => '用户不存在');
    }

    if (!is_password_pass($user['salt'], $user['password'], $input_password)) {
        return array('status' => RETURN_STATUS_FAIL, 'message' => '密码错误');
    }

    if ($user['status'] == USER_STATUS_FORBIDDEN) {
        return array('status' => RETURN_STATUS_FAIL, 'message' => '您的账户被禁用');
    }

    $_SESSION['user'] = $user;

    return array('status' => RETURN_STATUS_SUCCESS);
}

function add_user($username, $password, $dept_id, $status = 10)
{
    $salt = generate_salt();
    $password_md5 = generate_password($salt, $password);
    $user_id = Db::getInstance()->insert('user', array(
        'salt' => $salt,
        'username' => $username,
        'password' => $password_md5,
        'status' => $status,
    ));

    return $user_id;
}

function is_password_pass($salt, $expected, $user_input_password)
{
    $actual = generate_password($salt, $user_input_password);
    $expected .= "\0";
    $actual .= "\0";
    $expectedLength = strlen($expected);
    $actualLength = strlen($actual);
    $diff = $expectedLength - $actualLength;
    for ($i = 0; $i < $actualLength; $i++) {
        $diff |= (ord($actual[$i]) ^ ord($expected[$i % $expectedLength]));
    }
    return $diff === 0;
}

function generate_salt()
{
    return substr(uniqid(), -6);
}

function generate_password($salt, $password)
{
    return md5($salt . $password);
}

function find_user_by_username($username)
{
    return Db::getInstance()->query("select * from user where username=?", array($username));
}

function get_user_info($user_id, $column = null)
{
    $user_id = (int)$user_id;
    if ($column) {
        return Db::getInstance()->queryColumn("select `$column` from user where id=$user_id");
    } else {
        return Db::getInstance()->query("select * from user where id=$user_id");
    }
}

function is_success($return)
{
    if (isset($return['status']) && $return['status'] == RETURN_STATUS_SUCCESS) {
        return true;
    }

    return false;
}